package com.smart.opcda.service.listener;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.smart.common.springcontext.SpringContextManager;
import com.smart.opcda.dto.Group;
import com.smart.opcda.dto.Item;
import com.smart.opcda.dto.ReadDataResponse;
import com.smart.opcda.mqtt.MqttServerService;
import com.smart.opcda.service.OpcMemeryManager;
import com.smart.opcda.topic.ServerManager;
import com.smart.opcda.topic.TopicManager;
import com.smart.opcda.util.VariantUtil;
import javafish.clients.opc.asynch.AsynchEvent;
import javafish.clients.opc.asynch.OpcAsynchGroupListener;
import javafish.clients.opc.component.OpcGroup;
import javafish.clients.opc.component.OpcItem;
import javafish.clients.opc.variant.Variant;
import lombok.extern.slf4j.Slf4j;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author dengqiao
 * @date 2024/3/9 17:55
 */
@Slf4j
public class AsyncGroupListener implements OpcAsynchGroupListener {

    private String topicName;

    public AsyncGroupListener(String topicName) {
        this.topicName = topicName;
    }

    @Override
    public void getAsynchEvent(AsynchEvent asynchEvent) {
        try {
            MqttServerService mqttServerService = SpringContextManager.getBean("mqttServerService", MqttServerService.class);
            TopicManager topicManager = SpringContextManager.getBean("topicManager", TopicManager.class);
            ServerManager serverManager = SpringContextManager.getBean("serverManager", ServerManager.class);
            OpcMemeryManager opcMemeryManager = SpringContextManager.getBean("opcMemeryManager", OpcMemeryManager.class);
            Map<String, Map<String, ReadDataResponse>> opcGroupMap = opcMemeryManager.getOpcGroupMap();
            OpcGroup opcGroup = asynchEvent.getOPCGroup();
            Group group = serverManager.getGroupMap().get(opcGroup.getGroupName());
            String pubTopic = opcGroup.getGroupName();
            if (group != null && StrUtil.isNotBlank(group.getPubTopic())) {
                pubTopic = group.getPubTopic();
            }
            Map<String, ReadDataResponse> opcItemMap = opcGroupMap.get(opcGroup.getGroupName());
            if (opcItemMap == null) {
                opcItemMap = new ConcurrentHashMap<>();
            }
            List<OpcItem> list = opcGroup.getItems();
            List<ReadDataResponse> readDataResponses = new ArrayList<>();
            for (OpcItem opcItem : list) {
                String itemName = opcItem.getItemName().trim();
                String dataType = Variant.getVariantName(opcItem.getDataType());
                GregorianCalendar gregorianCalendar = opcItem.getTimeStamp();
                ReadDataResponse readDataResponse = new ReadDataResponse();
                Object value = VariantUtil.convertOpcValueToJava(opcItem);
                readDataResponse.setValue(value);
                readDataResponse.setDataType(dataType);
                readDataResponse.setItemQuality(opcItem.isQuality());
                readDataResponse.setItemId(itemName);
                if (gregorianCalendar != null) {
                    readDataResponse.setTimeStamp(gregorianCalendar.getTime());
                } else {
                    readDataResponse.setTimeStamp(new Date());
                }
                readDataResponse.setTopicName(topicName);
                readDataResponse.setItem(itemName.replaceAll(topicManager.getTopicMap().get(topicName).getAccessPath() + ".", ""));
                boolean isPush = true;
                if (opcItemMap.containsKey(opcItem.getItemName())) {
                    ReadDataResponse oldOpcItem = opcItemMap.get(opcItem.getItemName());
                    Object oldValue = oldOpcItem.getValue();
                    if (oldValue.toString().equals(value.toString())) {
                        isPush = false;
                    } else {
                        log.info("监测到item的值变化，groupId=" + opcGroup.getGroupName() + ",item=" + opcItem.getItemName() + ",oldvalue=" + oldValue.toString() + ",newValue=" + value.toString());
                    }
                } else {
                    log.info("监测到新的item，groupId=" + opcGroup.getGroupName() + ",item=" + opcItem.getItemName() + ",value=" + value.toString());
                }
                if (isPush) {
                    opcItemMap.put(opcItem.getItemName(), readDataResponse);
                    readDataResponses.add(readDataResponse);
                    Item item = serverManager.getItemMap().get(opcItem.getItemName());
                    if (item != null && StrUtil.isNotBlank(item.getPubTopic())) {
                        mqttServerService.publish(item.getPubTopic(), JSON.toJSONStringWithDateFormat(readDataResponse, "yyyy-MM-dd HH:mm:ss"));
                    }
                }
            }
            opcGroupMap.put(opcGroup.getGroupName(), opcItemMap);
            if (readDataResponses.size() > 0) {
                mqttServerService.publish(pubTopic, JSON.toJSONStringWithDateFormat(readDataResponses, "yyyy-MM-dd HH:mm:ss"));
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }
}
